﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Qing.Lang;

namespace Qing.Std {

    class Parallel : Native {
        public override string Name { get; set; } = "分支";
        public override string Desc { get; set; } = "参数1-代码块，返回任务；开启新的任务，执行参数1代码块中的代码";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count > 0) {
                if (args[0].Tp == TP.Brace) {
                    if (args[0].Tp.Equals(TP.Brace)) {
                        Task<Expr> t = new Task<Expr>(delegate () {
                            Env.Threads++;
                            try {
                                return Expr.EvalExprs(args[0].List!, ctx);
                            } finally {
                                Env.Threads--;
                            }

                        });

                        t.Start();
                        return new Expr(TP.Task, t);
                    }
                }
            }
            return Expr.Err("分支函数参数不足");
        }

    }


    class Spawn : Native {
        public override string Name { get; set; } = "并行";
        public override string Desc { get; set; } = "参数1-数组，可选参数2-逻辑，可选参数3-整数，返回任务数组；一次性开启多个任务，参数1是代码块数组，参数2表示是否等待所有任务结束（默认不等待），参数3设置等待的超时时间（毫秒）";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0) {
                bool wait = false;
                int timeout = 0;
                if (args.Count > 1) {
                    wait = args[1].ToBool();
                }
                if (args.Count > 2 && args[2].Tp == TP.Int) {
                    timeout = args[2].Int();
                }

                if (args[0].Tp == TP.Arr) {
                    foreach(Expr item in args[0].List!) {
                        if (item.Tp != TP.Brace) {
                            return Expr.Err("并发函数参数类型错误");
                        }
                    }

                    List<Task> taskList = new List<Task>();

                    foreach (Expr item in args[0].List!) {
                        Task<Expr> t = new Task<Expr>(delegate () {
                            Env.Threads++;                 
                            try {
                                return Expr.EvalExprs(item.List!, ctx);
                            } finally {
                                Env.Threads--;
                            }

                        });
                        taskList.Add(t);
                        t.Start();
                    }
                    if (wait) {
                        if (timeout > 0) {
                            Task.WaitAll(taskList.ToArray(), timeout);
                        } else {
                            Task.WaitAll(taskList.ToArray());
                        }
                    }
                    Expr ret = new Expr(TP.Arr,0, new List<Expr>());
                    foreach(var t in taskList) {
                        ret.List!.Add(new Expr(TP.Task, t));
                    }

                    return ret;
                }
            }


            return Expr.Err("并行函数参数错误");
        }

    }


    class Lock : Native {
        public override string Name { get; set; } = "并行锁";
        public override string Desc { get; set; } = "参数1-任意，参数2-代码块，返回任意；在多任务中，对参数1上锁，然后执行参数2代码块，用于多任务同步";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count >= 2 && args[1].Tp == TP.Brace) {
                Expr ans;
                lock (args[0]) {
                    ans = Expr.EvalExprs(args[1].List!, ctx);
                }
                return ans;
            }
            return Expr.Err("并行锁函数参数不足");
        }

    }


}
